package com.wjr.braveheart.ui.mvp.proxy;

import com.wjr.braveheart.ui.mvp.BasePresenter;
import com.wjr.braveheart.ui.mvp.IMvpBaseView;
import com.wjr.braveheart.ui.mvp.inject.InjectPresenter;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

public class MvpProxyImpl<V extends IMvpBaseView> implements IMvpProxy {

    private V mView;
    private List<BasePresenter> presenterList;

    public MvpProxyImpl(V view) {
        this.mView = view;
        this.presenterList = new ArrayList<>();
    }

    @Override
    public void createAndBindPresenter() {
        // 注入 Presenter 通过反射 (Dagger)
        Field[] fields = mView.getClass().getDeclaredFields();
        for (Field field : fields) {
            InjectPresenter injectPresenter = field.getAnnotation(InjectPresenter.class);
            if (injectPresenter != null) {
                // 创建注入
                Class<? extends BasePresenter> presenterClazz;
                // 判断类型 获取继承的父类，如果不是 继承 BasePresenter 抛异常
                // 编译器在运行的时候会对我们的泛型进行擦除（一般是针对系统的）
                presenterClazz = (Class<? extends BasePresenter>) field.getType();// 泛型擦除

                if (!BasePresenter.class.isAssignableFrom(presenterClazz)) {
                    // 这个 Class 是不是继承自 BasePresenter 如果不是抛异常
                    throw new RuntimeException("No support inject presenter type " + presenterClazz.getName());
                }
                BasePresenter basePresenter = null;
                try {
                    // 创建 Presenter 对象
                    basePresenter = presenterClazz.newInstance();
                    basePresenter.attach(mView);
                    field.setAccessible(true);
                    field.set(mView, basePresenter);
                    presenterList.add(basePresenter);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                // 检测 View 层是否实现了 BasePresenter 的View接口
                checkView(basePresenter);
            }
        }
    }

    @Override
    public void unbindPresenter() {
        for (BasePresenter presenter : presenterList) {
            presenter.detach();
        }
        presenterList.clear();
    }

    /**
     * 检测我们的 View 层是否实现了 BasePresenter 的View接口
     *
     * @param basePresenter
     */
    private void checkView(BasePresenter basePresenter) {
        // 获取 Presenter 的 View 接口
        Type[] params = ((ParameterizedType) basePresenter.getClass().getGenericSuperclass()).getActualTypeArguments();
        //两种方法(选择2)
        // 1.直接通过index获取该接口Class  Class viewClazz = ((Class) params[1]);
        //2.使用for循环通过对比找出接口Class
        for (Type param : params) {
            if (IMvpBaseView.class.isAssignableFrom((Class<?>) param)) {
                // 获取 View 层的所有接口
                Class[] ViewClasses = mView.getClass().getInterfaces();
                //  View 层没有实现该接口就抛出异常
                boolean isImplementsView = false;
                for (Class viewClass : ViewClasses) {
                    if (viewClass.isAssignableFrom((Class<?>) param)) {
                        isImplementsView = true;
                    }
                }
                if (!isImplementsView) {
                    throw new RuntimeException(mView.getClass().getSimpleName()
                            + " must implements "
                            + ((Class<?>) param).getName());
                }
            }
        }
    }
}
